#include "Common.h"
#include "Uart/AppLibUart_Base.hpp"
#include "Uart/AppLibUart_Chan0.hpp"

UART_CMD_LIST_HANDLE_s cmd_list_handle[] = 
{

};

#define CMD_LIST_SIZE       ARRAY_SIZE(cmd_list_handle)

static APP_LIB_UART_CFG_s gstUartCfg = 
{
    .eChannel = BSP_UART_CHANNEL_0,
    .iFd = -1,
    .pfSplitPkgCB = AppLibUart0_SplitPkg,
    .pfHandlePkgCB = AppLibUart0_HandlePkg,
};

static void AppLibUart0_DisplayPkg(UINT8 *buf, int size)
{
    int i = 0;
    int remain = size % 16;
	int integer = size / 16;

    printf("%s %d\n", __func__, __LINE__);
	if (integer) 
    {
		for (i = 0; i < integer; i++) 
        {
			printf("%02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x\n",
				buf[i*16],      buf[i*16 + 1],  buf[i*16 + 2],  buf[i*16 + 3], buf[i*16 + 4],  buf[i*16 + 5],
                buf[i*16 + 6],  buf[i*16 + 7],  buf[i*16 + 8],  buf[i*16 + 9], buf[i*16 + 10], buf[i*16 + 11], 
                buf[i*16 + 12], buf[i*16 + 13], buf[i*16 + 14], buf[i*16 + 15]);
		}
	}
	
    if (remain) 
    {
        for (i = 0; i < remain; i++)
        {
            printf("%02x, ", buf[integer * 16 + i]);
        }

        printf("\n");
    }
}


UINT8 AppLibUart0_CheckSum(UINT8 *data, int len)
{
	int i;
	UINT8 sum = 0;

	for (i = 0; i < len; i++) {
		sum += data[i];
	}
	sum =sum^0x01;
	return sum;
}

void AppLibUart0_HandlePkg(IN UINT8 *pucPacket, IN UINT16 usLen)
{
	int payload_len = 0;
	int cmd = 0;
	int checksum = 0;

	//HEAD[2 BYTES] + CMD[1 BYTES] + SIZE[2 BYTES] + DATA[N BYTES] + CHECKSUM[1 BYTES]
	if (pucPacket[0] != UART_CHANNEL0_COM_HEAD0 || pucPacket[1] != UART_CHANNEL0_COM_HEAD1) {
		LOG_ERROR("header error!(0x%02x 0x%02x)\n", pucPacket[0], pucPacket[1]);
		return;
	}

	cmd 		= pucPacket[2];
	payload_len = (pucPacket[3] << 8 ) | pucPacket[4];
	checksum    = AppLibUart0_CheckSum(&pucPacket[5], payload_len);
	if (checksum != pucPacket[payload_len + 5]) {
		LOG_ERROR("cmd:0x%x payload_len:%d checksum:0x%x-0x%x", cmd, payload_len, checksum, pucPacket[payload_len + 5]);
		AppLibUart0_DisplayPkg(pucPacket, usLen);
		return;
	}

	LOG_INFO("[RecvHandle]cmd:0x%x", cmd);

#if 0
	/* run function callback by cmd */
	for (index = 0; index < CMD_LIST_SIZE; index++) {
		if (cmd_list_handle[index].cmd == pucPacket[2]) 
		{
    		cmd_list_handle[index].func(pucPacket[2], &pucPacket[5], payload_len);
			break;
		}
	}
#endif
}

static int AppLibUart0_SearchPackage(APP_LIB_UART_MULT_PKG_s *mpkg, UINT8 *pkg)
{
	int i, size = 0, ret = -1;

	//LOG_DEBUG("offset=%d, end=%d\n", mpkg->offset, mpkg->offset + mpkg->size);
	for (i = mpkg->offset; i < (mpkg->offset + mpkg->size); i++) 
    {
		if ((APP_LIB_UART_PROTOCOL_HEAD0 != mpkg->buf[i]) || (APP_LIB_UART_PROTOCOL_HEAD1 != mpkg->buf[i+1])) 
        {
            continue;
        }

        size = (mpkg->buf[i+3] << 8) + mpkg->buf[i+4];
        size += 6;// head[2 bytes]+cmd[1 byte]+size[2 bytes]+checksm[1 byte]

        //LOG_DEBUG("request end=%d, limit end %d\n", i + size, mpkg->offset + mpkg->size);
        if ((i + size) <= (mpkg->offset + mpkg->size)) 
        {
            memcpy(pkg, &(mpkg->buf[i]), size);

            mpkg->size -= size;
            mpkg->offset += size;

            ret = size;
        } 
        else 
        {
            //AppLibUart_DisplayPkg(&mpkg->buf[mpkg->offset], mpkg->size);

            // move to vaild data offset
            mpkg->size   = mpkg->size - (i - mpkg->offset);
            mpkg->offset = i;

            ret = 0;
            //LOG_DEBUG("offset=%d, end=%d\n", mpkg->offset, mpkg->offset + mpkg->size);
            //AppLibUart_DisplayPkg(&mpkg->buf[mpkg->offset], mpkg->size);
        }
	}

	return ret;
}

//处理解析，以及命令处理回调
void AppLibUart0_SplitPkg(IN UINT8 *pucPacket, IN UINT16 usLen)
{
	int pkg_size = 0;
	UINT8 tmp_package[UART_RX_BUFF_SIZE] = {0};
    APP_LIB_UART_MULT_PKG_s *mpkg = &gstUartCfg.stPackage;

    //AppLibUart_DisplayPkg(tmp_buffer, rx_size);
    //LOG_DEBUG("offset=%d, size=%d, rx_size=%d\n", mpkg->offset, mpkg->size, rx_size);

    if ((mpkg->size + usLen) > UART_RX_MULT_SIZE) 
    {
        LOG_DEBUG("buffer is full:%d-%d", mpkg->size, usLen);
        memset(mpkg, 0, sizeof(APP_LIB_UART_MULT_PKG_s));
    }

    memcpy(&mpkg->buf[mpkg->offset + mpkg->size], pucPacket, usLen);
    mpkg->size += usLen;

    //LOG_DEBUG("after  memcpy: len %d\n", mpkg->size);
    //AppLibUart_DisplayPkg(mpkg->buf, mpkg->size);

    do {
        memset(tmp_package, 0, sizeof(tmp_package));
        pkg_size = AppLibUart0_SearchPackage(mpkg, tmp_package);
        //LOG_DEBUG("mpkg: offset=%d, size=%d, pkg_size=%d\n", mpkg->offset, mpkg->size, pkg_size);

        if (pkg_size == 0 || pkg_size == -1)
        {
            break;
        }

        //LOG_DEBUG("cmd=0x%02x, len %d\n", tmp_package[2], pkg_size);
        //AppLibUart_DisplayPkg(tmp_package, pkg_size);
        AppLibUart_PushPacket(gstUartCfg.eChannel + APP_LIB_MSG_TYPE_SPLITE, tmp_package, pkg_size);
    } while (pkg_size > 0);

    //LOG_DEBUG("before : offset=%d, size=%d\n", mpkg->offset, mpkg->size);
    if (pkg_size == 0)
    {
        memcpy(&mpkg->buf[0], &mpkg->buf[mpkg->offset], mpkg->size);
        mpkg->offset = 0;
        //LOG_DEBUG("contains vaild head: move mpkg\n");
    }
    else
    {
        //LOG_DEBUG("no vaild head: reset mpkg\n");
        memset(mpkg, 0, sizeof(APP_LIB_UART_MULT_PKG_s));
    }

    //LOG_DEBUG("after  :offset=%d, size=%d\n", mpkg->offset, mpkg->size);
    return;
}

ULONG AppLibUart0_Open(void)
{
    return AppLibUart_Register(&gstUartCfg);
}
